

--[[
    handle管理器，一套管理客户端和服务器之间对象的逻辑
    可以注册不同类型的对象
    包含客户端的同步逻辑
    包含保存和回复模板，可参考character和citem
]]


local handle_manager = {}
base.handle_manager = handle_manager
handle_manager.mt_map = {}     -- 存储不同类型对象的元表
handle_manager.handle_map = {} -- 存储所有已创建对象的映射表
handle_manager.handle_count = {} -- 记录每种类型对象的计数

local handle_manager_mt = {} -- 基础元表，所有通过handle_manager创建的对象都会继承此元表

--初始化
handle_manager_mt.inited = false
--移除
handle_manager_mt.removed = false

-- 向客户端同步数据
function handle_manager_mt:sync(data)
    --log.info('handle_manager_mt:sync', self.sync_id, type(data) == 'table' and utils.get_show_table_str(data,5) or data, debug.traceback())
    base.game:ui(self.sync_id)(data)
end
function handle_manager_mt:sync_message( sync_key, data)
    --log.info('handle_manager_mt:sync_message', self.sync_id, sync_key,type(data) == 'table' and utils.get_show_table_str(data) or data, debug.traceback())
    base.game:ui(self.sync_id)({
        sync_key,
        self.handle,
        data,
    })
end

function handle_manager_mt:sync_relink()
    if not self.inited then
        return
    end
    self:sync_create()
    if self.on_sync_relink then
        self:on_sync_relink()
    end
end

-- 同步创建对象到客户端
function handle_manager_mt:sync_create(data)
    local sync_data = {
        self.sync_key.create, -- 创建操作的标识符
        self.handle,          -- 对象的唯一标识
    }
    sync_data[3] = self:OnSyncCreate() -- 添加自定义创建时同步的数据
    self:sync(sync_data)
end

-- 同步移除对象到客户端
function handle_manager_mt:sync_remove()
    if not self.inited then
        return
    end
    local sync_data = {
        self.sync_key.remove, -- 移除操作的标识符
        self.handle,          -- 对象的唯一标识
    }
    if self.on_sync_remove then
        sync_data[3] = self:on_sync_remove(sync_data) -- 添加自定义移除时同步的数据
    end
    self:sync(sync_data)
end

-- 同步设置对象属性到客户端
-- 可传入多个属性名，会将这些属性的当前值同步到客户端
--传如单个参数，参数是单个key
function handle_manager_mt:sync_set_value(key)
    if not self.inited then
        return
    end
    local send = {
        self.sync_key.set,  -- 设置属性操作的标识符
        self.handle,        -- 对象的唯一标识
    }
    local count = 0
    local i = 1
    count = count + 1
    send[3+i*2-1] = key       -- 属性名
    if type(key) == 'table' then
        local value = self
        for k,v in ipairs(key) do
            value = value[v]
        end
        send[3+i*2] = value -- 属性值
    else
        send[3+i*2] = self[key] -- 属性值
    end
    send[3] = count
    self:sync(send)
end
--传入单个参数，参数是key-list
function handle_manager_mt:sync_set_list(args)
    if not self.inited then
        return
    end
    local send = {
        self.sync_key.set,  -- 设置属性操作的标识符
        self.handle,        -- 对象的唯一标识
    }
    local count = 0
    for i, key in ipairs(args) do
        count = count + 1
        send[3+i*2-1] = key       -- 属性名
        if type(key) == 'table' then
            local value = self
            for k,v in ipairs(key) do
                value = value[v]
            end
            send[3+i*2] = value -- 属性值
            --log.info('sync_set_list A', self, key, value, debug.traceback())
        else
            send[3+i*2] = self[key] -- 属性值
            --log.info('sync_set_list B', self, key, self[key], debug.traceback())
        end
    end
    send[3] = count
    self:sync(send)
end
--传入多个参数，每个参数都是key
function handle_manager_mt:sync_set(...)
    if not self.inited then
        return
    end
    local send = {
        self.sync_key.set,  -- 设置属性操作的标识符
        self.handle,        -- 对象的唯一标识
    }
    local count = 0
    local args = {...}
    for i, key in ipairs(args) do
        count = count + 1
        send[3+i*2-1] = key       -- 属性名
        if type(key) == 'table' then
            local value = self
            for k,v in ipairs(key) do
                value = value[v]
            end
            send[3+i*2] = value -- 属性值
            --log.info('sync_set A', self, key, value, debug.traceback())
        else
            send[3+i*2] = self[key] -- 属性值
            --log.info('sync_set B', self, key, self[key], debug.traceback())
        end
    end
    send[3] = count
    --log.info('[handle_manager] sync_set', utils.get_show_table_str(send))
    self:sync(send)
end

-- 创建对象时的自定义同步数据处理
function handle_manager_mt:OnSyncCreate()
    if self.on_sync_create then
        return self:on_sync_create()
    end
end

-- 可用于处理多级继承，移除对象时的回调
function handle_manager_mt:OnRemove()
    if self.on_remove then
        self:on_remove()
    end
end

-- 可用于处理多级继承，初始化对象时的回调
function handle_manager_mt:OnInit()
    if self.on_init then
        self:on_init()
    end
end

-- 移除一个对象，会调用OnRemove回调
function handle_manager_mt:remove()
    if self.removed then
        return -- 防止重复移除
    end
    self.removed = true
    self:OnRemove()
    if self.handle_map[self.handle] then
        self.handle_map[self.handle] = nil
    end
    self:sync_remove()
end

-- 初始化一个对象，分配handle并添加到handle_map中
function handle_manager_mt:init()
    if self.inited then
        return
    end
    handle_manager.handle_count[self.handle_type] = handle_manager.handle_count[self.handle_type] +1
    local handle = handle_manager.handle_count[self.handle_type]
    handle_manager.handle_map[self.handle_type][handle] = self
    self.handle = handle
    self:OnInit()
    self.inited = true
    self:sync_create() -- 自动同步创建到客户端
end

-- 注册一个新的对象类型，返回该类型的元表
-- key: 对象类型的唯一标识符
function handle_manager:register(key)
    if not key then
        log.info("Error: Missing required arguments for handle_manager:create (key)")
        key = 'default' -- 防止提示，总之跑起来
    end
    if handle_manager.mt_map[key] then
        return handle_manager.mt_map[key] -- 如果已存在该类型，直接返回
    end
    self.handle_map[key] = {}  -- 初始化该类型的对象映射表
    self.handle_count[key] = 0 -- 初始化该类型的对象计数
    local mt = {
        sync_id = 'ho_' .. key, -- 同步ID前缀
        sync_key = {            -- 同步操作的标识符
            create = 1,
            remove = 2,
            set = 3,
        },
        relink_sort_id = 100,--重连时排序id
        handle_type = key,      -- 对象类型
        handle_map = self.handle_map[key], -- 该类型的对象映射表引用
    }
    setmetatable(mt, {__index = handle_manager_mt}) -- 继承基础元表
    handle_manager.mt_map[key] = mt -- 保存该类型的元表

    return mt
end

function handle_manager:get_all_handle(key)
    if not handle_manager.handle_map[key] then
        log.error('handle_manager:get_all_handle', key, 'not found')
        return
    end
    return handle_manager.handle_map[key]
end

function handle_manager:get(key, handle)
    if not handle then
        return nil
    end
    if not handle_manager.handle_map[key] then
        return nil
    end
    return handle_manager.handle_map[key][handle]
end

function handle_manager:sync_relink()
    local count = 0
    local pulse = 0.1

    local list = {}

    for key,v in pairs(handle_manager.handle_map) do
        list[#list+1] = {
            map = v,
            sort_id = handle_manager.mt_map[key] and handle_manager.mt_map[key].relink_sort_id or 100,
        }
    end
    table.sort(list, function(a,b)
        return (a.sort_id or 100) < (b.sort_id or 100)
    end)
    for _,v in ipairs(list) do
        for handle,target in pairs(v.map) do
            count = count + 1
            base.wait( count * pulse, function()
                target:sync_relink()
            end)
        end
    end
    return count, count/1000
end


-- 以下是被注释掉的玩家连入事件处理代码
--base.game:event('玩家-连入', function(_,player)
--    local list = {}
--    for key,v in pairs(handle_manager.handle_map) do
--        list[#list+1] = key
--    end
--    player:ui('handle_manager_key')(list)
--end)

